﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json;
using Tzx.Tools.Payroll2Images.Exe.Api;
using Tzx.Utilities;

namespace Tzx.Tools.Payroll2Images.Exe.FilesSender
{
    /// <summary>
    /// 
    /// </summary>
    public class Sender
    {

        #region 构造

        private const string SubItem_文件路径地址全名 = "文件路径地址全名 ";
        private const string SubItem_文件短名 = "文件短名";
        private const string SubItem_提交 = "提交";
        private const string SubItem_发送状态 = "发送状态";
        private const string SubItem_阅读状态 = "阅读状态";
        private const string SubItem_撤回 = "撤回";
        private const string SubItem_备注 = "备注";
        private const string SubItem_任务 = "task_id";

        /// <summary>
        /// 初始设置ListView控件
        /// </summary>
        public static void InitListView(ListView LvFiless)
        {
            // 初始化ListView
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_文件路径地址全名, Width = 120 });
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_文件短名, TextAlign = HorizontalAlignment.Left, Width = 200 });
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_提交, TextAlign = HorizontalAlignment.Center, Width = 70 });
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_发送状态, TextAlign = HorizontalAlignment.Center, Width = 70 });
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_阅读状态, TextAlign = HorizontalAlignment.Center, Width = 70 });
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_撤回, TextAlign = HorizontalAlignment.Center, Width = 70 });
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_备注, TextAlign = HorizontalAlignment.Left, Width = 140 });
            LvFiless.Columns.Add(new ColumnHeader() { Text = SubItem_任务, TextAlign = HorizontalAlignment.Left, Width = 90 });

            //
            LvFiless.CheckBoxes = true;
            LvFiless.FullRowSelect = true;
            LvFiless.GridLines = true;
            LvFiless.MultiSelect = false;
            LvFiless.View = System.Windows.Forms.View.Details;
        }

        #endregion

        #region 遍历列表Item调用API(四个接口调用)

        /// <summary>
        /// 显示YesOrNo文本
        /// </summary>
        private static string GetYesNoText(YesOrNo yesno)
        {
            return
                yesno == YesOrNo.Default
                    ? string.Empty
                    : yesno.ToString();
        }

        /// <summary>
        /// 显示各状态
        /// </summary>
        /// <param name="lvi"></param>
        /// <param name="status"></param>
        private static void ShowStatus(ListViewItem lvi, ApiStatus status)
        {
            //设置SubItems颜色会闪烁
            lvi.SubItems[SubItem_提交].Text = GetYesNoText(status.status_submit_send);
            lvi.SubItems[SubItem_发送状态].Text = GetYesNoText(status.status_progress);
            lvi.SubItems[SubItem_阅读状态].Text = GetYesNoText(status.status_result_read);
            lvi.SubItems[SubItem_撤回].Text = GetYesNoText(status.status_recall);
            lvi.SubItems[SubItem_备注].Text = status.remark_text;
            lvi.SubItems[SubItem_任务].Text = status.task_id;
        }

        /// <summary>
        /// 1.提交选中的发送
        /// </summary>
        public static void Do_Submit_Checked(ListView LvFiless,ProgressBar progressBar1,Label lblProgress)
        {
            List<ListViewItem> list = GetCheckedItems(LvFiless);
            int p_count = list.Count; //总数
            int p_index = 0; //第几个
            foreach (ListViewItem lvi in list)
            {
                //进度
                progressBar1.Value = (int)(((double)(p_index++) / (double)p_count) * 100.00d); //进度条
                lblProgress.Text = String.Format("{0}/{1}", p_index, p_count); //进度

                //滚动选中
                int idx = lvi.Index;
                lvi.Selected = true; //选中行,灰色
                LvFiless.EnsureVisible(idx); //确保当前选定项是可见的,必要时使控件内容滚动

                //
                string file = lvi.Text;
                ApiStatus status = lvi.Tag as ApiStatus;
                if (status == null)
                {
                    string msg = "第" + (idx + 1).ToString() + "个内置Tag数据为空";
                    LogFile.Instance().LogText(msg);

                    //MessageBox.Show(msg, Title, MessageBoxButtons.OK, MessageBoxIcon.Error); //出错
                    ApiStatus error = new ApiStatus() {};
                    error.status_submit_send=YesOrNo.Error;
                    error.remark_text = msg;
                    ShowStatus(lvi, error); //程序异常错误

                    return;
                }

                if (status.status_submit_send == YesOrNo.Yes)
                {
                    continue; //已提交,就不用再次提交了,跳过
                }

                //API提交
                YesOrNo yn_submit = ApiCall.Do_SubmitSend(file, ref status); //提交一行API发送
                ShowStatus(lvi, status); //更新提交发送状态
                if (yn_submit != YesOrNo.Yes)
                {
                    continue; //提交失败
                }

                //如果提交发送成功则转移文件
                if (status.status_submit_send == YesOrNo.Yes)
                {
                    MoveSendedFile(file);
                }

                Application.DoEvents(); //放手
            } //foreach

            progressBar1.Value = (int)(((double)(p_index) / (double)p_count) * 100.00d); //进度条
            SaveTempFile(LvFiless);//保存临时文件状态
            Thread.Sleep(100);
        }

        /// <summary>
        /// 2.更新选中的发送状态
        /// </summary>
        /// <param name="scroll">是否滚动</param>
        public static void Do_RenewSendStatus_Checked(bool scroll, ListView LvFiless, ProgressBar progressBar1, Label lblProgress)
        {
            List<ListViewItem> list = GetCheckedItems(LvFiless);
            int p_count = list.Count;//总数
            int p_index = 0;//第几个

            //
            foreach (ListViewItem lvi in list)
            {
                progressBar1.Value = (int)(((double)(p_index++) / (double)p_count) * 100.00d);//进度条
                lblProgress.Text = String.Format("{0}/{1}", p_index, p_count);//进度

                int idx = lvi.Index;
                lvi.Selected = true; //选中行,灰色
                if (scroll)
                {
                    LvFiless.EnsureVisible(idx); //确保当前选定项是可见的,必要时使控件内容滚动
                }

                ApiStatus status = lvi.Tag as ApiStatus;
                if (status == null)
                {
                    ZBug.Log("发送进度,没有内置状态对象错误,跳过");
                    continue;
                }
                if (status.status_submit_send != YesOrNo.Yes)
                {
                    ZBug.Log("没有提交发送过,无需获取进度");
                    continue;
                }
                if (status.status_progress == YesOrNo.Yes)
                {
                    ZBug.Log("发送进度已经完成了,无需再更新发送进度");
                    continue;
                }

                //string task_id = status.task_id;

                //API
                YesOrNo success = ApiCall.Do_GetSendProgress(ref status);//, out api_message
                ShowStatus(lvi, status);
                if (success == YesOrNo.Error)
                {
                    //访问出错
                    continue;
                }

                Application.DoEvents();//放手
            }//foreach

            progressBar1.Value = (int)(((double)(p_index) / (double)p_count) * 100.00d);//进度条
            SaveTempFile(LvFiless);//保存临时文件状态
            Thread.Sleep(100);
        }

        /// <summary>
        /// 3.更新选中的阅读状态
        /// </summary>
        public static void Do_RenewReadStatus_Checked(ListView LvFiless, ProgressBar progressBar1, Label lblProgress)
        {
            List<ListViewItem> list = GetCheckedItems(LvFiless);
            int p_count = list.Count; //总数
            int p_index = 0; //第几个

            foreach (ListViewItem lvi in list)
            {
                progressBar1.Value = (int)(((double)(p_index++) / (double)p_count) * 100.00d); //进度条
                lblProgress.Text = String.Format("{0}/{1}", p_index, p_count); //进度

                int idx = lvi.Index;
                lvi.Selected = true; //选中行,灰色
                LvFiless.EnsureVisible(idx); //确保当前选定项是可见的,必要时使控件内容滚动

                ApiStatus status = lvi.Tag as ApiStatus;
                if (status == null)
                {
                    LogFile.Instance().LogText("结果阅读状态,没有内置状态对象错误,跳过");
                    continue;
                }
                if (status.status_submit_send != YesOrNo.Yes)
                {
                    continue; //无提交发送
                }
                if (status.status_progress != YesOrNo.Yes)
                {
                    continue; //发送进度未完成
                }
                if (status.status_result_read == YesOrNo.Yes)
                {
                    continue; //已读了
                }
                if (status.status_recall == YesOrNo.Yes)
                {
                    continue; //已经撤回了
                }

                //string task_id = status.task_id;
                //string useridss = string.Format("{0}", status.user_idss); //发送用户清单

                //API
                YesOrNo readed_yesno = ApiCall.Do_GetResult_IsReaded(ref status);//, out api_message
                ShowStatus(lvi, status);
                if (readed_yesno == YesOrNo.Error)
                {
                    continue; //访问出错,继续下一条
                }
                Application.DoEvents(); //放手
            } //foreach

            progressBar1.Value = (int)(((double)(p_index++) / (double)p_count) * 100.00d); //进度条
            SaveTempFile(LvFiless);//保存临时文件状态
            Thread.Sleep(100);
        }

        /// <summary>
        /// 4.撤回选中的消息
        /// </summary>
        public static void Do_Recall_Checked(ListView LvFiless, ProgressBar progressBar1, Label lblProgress)
        {
            List<ListViewItem> list = GetCheckedItems(LvFiless);
            int p_count = list.Count;//总数
            int p_index = 0;//第几个
            foreach (ListViewItem lvi in list)
            {
                progressBar1.Value = (int)(((double)(p_index++) / (double)p_count) * 100.00d);//进度条
                lblProgress.Text = String.Format("{0}/{1}", p_index, p_count);//进度

                int idx = lvi.Index;
                lvi.Selected = true; //选中行,灰色
                LvFiless.EnsureVisible(idx);//确保当前选定项是可见的,必要时使控件内容滚动

                ApiStatus status = lvi.Tag as ApiStatus;
                if (status == null)
                {
                    LogFile.Instance().LogText("没有内置状态对象错误,跳过撤回");
                    continue;
                }
                if (status.status_submit_send != YesOrNo.Yes)
                {
                    LogFile.Instance().LogText("没有提交发送过,无需撤回");
                    continue;
                }
                if (status.status_progress != YesOrNo.Yes)
                {
                    LogFile.Instance().LogText("未发送成功,无需撤回");
                    continue;
                }
                if (status.status_recall == YesOrNo.Yes)
                {
                    LogFile.Instance().LogText("已经撤回,无需再次撤回");
                    continue;
                }

                //string task_id = status.task_id;

                //API
                YesOrNo yn = ApiCall.Do_Recall(ref status);//, out api_message
                ShowStatus(lvi, status);
                if (yn == YesOrNo.Error)
                {
                    //访问出错
                    continue;
                }

                //撤回状态

                Application.DoEvents();//放手
            }//foreach

            progressBar1.Value = (int)(((double)(p_index) / (double)p_count) * 100.00d);//进度条
            SaveTempFile(LvFiless);//保存临时文件状态
            Thread.Sleep(100);
        }

        #endregion

        #region private辅助方法

        /// <summary>
        /// 状态ApiStatus列表,填充到ListView控件
        /// </summary>
        /// <param name="apiStatuses"></param>
        public static void FillApiStatusItems(IEnumerable<ApiStatus> apiStatuses,ListView LvFiless)
        {
            LvFiless.Items.Clear();//清空

            List<ListViewItem> list = GetItemListByStatuss(apiStatuses); //转换成列表控件          
            foreach (ListViewItem li in list)
            {
                LvFiless.Items.Add(li);
            }
        }

        /// <summary>
        /// 状态ApiStatus列表,转换成ListView控件的Item
        /// </summary>
        /// <param name="apiStatuses"></param>
        /// <returns></returns>
        private static List<ListViewItem> GetItemListByStatuss(IEnumerable<ApiStatus> apiStatuses)
        {
            List<ListViewItem> list = new List<ListViewItem>();
            foreach (ApiStatus status in apiStatuses)
            {
                //
                string short_name = status.file_short_name;

                ListViewItem item = new ListViewItem();
                item.Text = status.file_full_path_name; //文件路径全名
                item.Checked = status.is_checked;
                item.Tag = status;//new ApiStatus(file_full_name); //状态数据
                list.Add(item);

                //item.UseItemStyleForSubItems = false;//单独设置样式ListViewSubItem

                //0,原Text

                //1,                    
                item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = short_name, Name = SubItem_文件短名 });
                item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = GetYesNoText(status.status_submit_send), Name = SubItem_提交 });
                item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = GetYesNoText(status.status_progress), Name = SubItem_发送状态 });
                item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = GetYesNoText(status.status_result_read), Name = SubItem_阅读状态 });
                item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = GetYesNoText(status.status_recall), Name = SubItem_撤回 });
                item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = status.remark_text, Name = SubItem_备注 });
                item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = status.task_id, Name = SubItem_任务 });
                //item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = status.media_id, Name =  });
                //item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = status.user_idss, Name =  });

            } //foreach

            return list;
        }

        /// <summary>
        /// 文件夹里的文件,填充到ListView控件
        /// </summary>
        public static void FillFileSs(string folder,ListView lvFiless)
        {
            lvFiless.Items.Clear();//清空

            string[] filess = Directory.GetFiles(folder, "*");

            #region 转换
            //List<ListViewItem> list = GetItemListByFiles(filess); //转换成列表控件
            List<ApiStatus> statuses = ConvertFilesToApiStatus(filess);
            List<ListViewItem> list = GetItemListByStatuss(statuses); //转换成列表控件
            #endregion

            foreach (ListViewItem li in list)
            {
                lvFiless.Items.Add(li);
            }
        }

        /// <summary>
        /// 文件列表,转换成ListView控件的Item
        /// </summary>
        [Obsolete("去统一",true)]
        private static List<ListViewItem> GetItemListByFiles(IEnumerable<string> filess)
        {
            List<ListViewItem> list = new List<ListViewItem>();
            foreach (string file in filess)
            {
                string file_full_name = file;
                if (
                    file_full_name.EndsWith(".jpg")  ||
                    file_full_name.EndsWith(".jpeg") ||
                    file_full_name.EndsWith(".png")  ||
                    file_full_name.EndsWith(".gif")  ||
                    file_full_name.EndsWith(".bmp")
                    )
                {
                    //
                    string short_name = Path.GetFileName(file_full_name);

                    ListViewItem item = new ListViewItem();
                    item.Text = file_full_name;  //文件路径全名
                    item.Checked = true;    //默认选中
                    //item.Tag = new ApiStatus(file_full_name);//状态数据
                    item.Tag = new ApiStatus() { file_full_path_name = file_full_name };//状态数据
                    list.Add(item);

                    //item.UseItemStyleForSubItems = false;//单独设置样式ListViewSubItem

                    //0,原Text

                    //1,                    
                    item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = short_name, Name = SubItem_文件短名 });
                    item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = "", Name = SubItem_提交 });
                    item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = "", Name = SubItem_发送状态 });
                    item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = "", Name = SubItem_阅读状态 });
                    item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = "", Name = SubItem_撤回 });
                    item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = "", Name = SubItem_备注 });
                    item.SubItems.Add(new ListViewItem.ListViewSubItem() { Text = "", Name = SubItem_任务 });
                }
            }//foreach

            return list;
        }

        /// <summary>
        /// 文件转换成状态对象
        /// </summary>
        private static List<ApiStatus> ConvertFilesToApiStatus(IEnumerable<string> filess)
        {
            List<ApiStatus> list = new List<ApiStatus>();
            foreach (string file in filess)
            {
                string file_full_name = file;
                if (
                    file_full_name.EndsWith(".jpg") ||
                    file_full_name.EndsWith(".jpeg") ||
                    file_full_name.EndsWith(".png") ||
                    file_full_name.EndsWith(".gif") ||
                    file_full_name.EndsWith(".bmp")
                    )
                {
                    string short_name = Path.GetFileName(file_full_name);
                    ApiStatus status = new ApiStatus();
                    status.file_full_path_name = file_full_name;
                    status.file_short_name = short_name;
                    status.is_checked = true;//默认选中
                    list.Add(status);
                    //item.UseItemStyleForSubItems = false;//单独设置样式ListViewSubItem
                }
            }//foreach

            return list;
        }

        /// <summary>
        /// 勾选列表
        /// </summary>
        public static List<ListViewItem> GetCheckedItems(ListView LvFiless)
        {
            List<ListViewItem> list = new List<ListViewItem>();
            foreach (ListViewItem lvi in LvFiless.Items)
            {
                if (lvi.Checked)
                {
                    list.Add(lvi);
                }
            }
            return list;
        }

        /// <summary>
        /// 文件夹名称
        /// </summary>
        private static string sub_folder = "已提交_" + DateTime.Now.ToString("yyyyMMddHHmmss");

        /// <summary>
        /// 移动已提交文件
        /// </summary>
        /// <param name="file"></param>
        private static void MoveSendedFile(string file)
        {
            //
            if (!File.Exists(file))
            {
                LogFile.Instance().LogText("文件不存在", file);
                return;
            }

            string only_file = string.Format("{0}", Path.GetFileName(file));
            string only_path = string.Format("{0}", Path.GetDirectoryName(file));

            //
            string dir = Path.Combine(only_path, sub_folder);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            string file2 = Path.Combine(dir, only_file);
            File.Move(file, file2);
        }

        /// <summary>
        /// 暂存临时文件名
        /// </summary>
        public const string TEMP_FILE_NAME_SENDER = "_sender_.tmp";

        /// <summary>
        /// 暂存临时文件
        /// </summary>
        public static bool SaveTempFile(ListView LvFiless,out string message)
        {
            //
            message = null;

            //
            List<ApiStatus> list = new List<ApiStatus>();
            foreach (ListViewItem li in LvFiless.Items)
            {
                ApiStatus status = li.Tag as ApiStatus;
                if (status != null)
                {
                    list.Add(status);
                }
            }//foreach

            //
            string json_file = Path.Combine(Application.StartupPath, TEMP_FILE_NAME_SENDER);
            string json = JsonConvert.SerializeObject(list);//Formatting.Indented
            if (File.Exists(TEMP_FILE_NAME_SENDER))
            {
                File.Delete(TEMP_FILE_NAME_SENDER);
            }
            File.WriteAllText(json_file, json, Encoding.Default);

            //返回
            return true;
        }

        /// <summary>
        /// 暂存临时文件
        /// </summary>
        private static void SaveTempFile(ListView LvFiless)
        {
            string message = null;
            bool ok = SaveTempFile(LvFiless,out message);
            return;
        }

        /// <summary>
        /// 从临时文件中加载
        /// </summary>
        public static bool LoadTemplate(ListView LvFiless,out string message)
        {
            //加载
            string json_file = Path.Combine(Application.StartupPath, TEMP_FILE_NAME_SENDER);
            if (!File.Exists(json_file))
            {
                message = "没有保存的临时文件【" + TEMP_FILE_NAME_SENDER + "】";
                return false;
            }

            //
            List<ApiStatus> list = null;
            try
            {
                string json = File.ReadAllText(json_file, Encoding.Default);
                list = JsonConvert.DeserializeObject<List<ApiStatus>>(json);
            }
            catch (Exception ex)
            {
                message = "载入临时文件出错:" + ex.Message;
                return false;
            }
            if (list == null)
            {
                message = "解析载入临时文件为空";
                return false;
            }

            //清空并填充
            LvFiless.Items.Clear();
            FillApiStatusItems(list, LvFiless);

            //
            message = null;
            return true;
        }

        #endregion

        /// <summary>
        /// 拼接ListView全部行文本含标题
        /// </summary>
        public static string GetListViewText(ListView LvFiless)
        {
            string fullText = string.Empty;
            for (int itemIdx = 0; itemIdx < LvFiless.Items.Count; itemIdx++)
            {
                string singleLine = string.Empty;

                //标题行
                if (itemIdx == 0)
                {
                    for (int colIdx = 0; colIdx < LvFiless.Columns.Count; colIdx++)
                    {
                        singleLine = singleLine + LvFiless.Columns[colIdx].Text + "\t";
                    }
                    singleLine = singleLine.Substring(0, singleLine.Length - 1) + "\r\n";
                }

                //内容行
                for (int colIdx = 0; colIdx < LvFiless.Columns.Count; colIdx++)
                {
                    singleLine = singleLine + LvFiless.Items[itemIdx].SubItems[colIdx].Text.Replace("\n", "") + "\t";
                }//for

                fullText = fullText + singleLine.Substring(0, singleLine.Length - 1) + "\r\n";
            }//for

            return fullText;
        }

        /// <summary>
        /// 拼接ListView选定行文本
        /// </summary>
        public static string GetListViewRowText(ListView LvFiless, out List<int> rowIndexList)
        {
            StringBuilder builder = new StringBuilder();
            rowIndexList = new List<int>(); //List<int> 
            foreach (ListViewItem item in LvFiless.SelectedItems)
            {
                string singleLine = string.Empty;

                //内容行
                for (int colIdx = 0; colIdx < LvFiless.Columns.Count; colIdx++)
                {
                    singleLine = singleLine + item.SubItems[colIdx].Text.Replace("\n", "") + "\t";
                }
                builder.AppendLine(singleLine.Substring(0, singleLine.Length - 1));
                rowIndexList.Add(item.Index);
            }//foreach

            //
            string fullText = builder.ToString();
            return fullText;
        }


    }
}
